#!/usr/bin/env python
# -*- coding: utf-8 -*-
from __future__ import unicode_literals

import time
import random
import string
import StringIO
from PIL import Image, ImageFont, ImageDraw
# import chardet
from email.mime.base import MIMEBase
from email.mime.multipart import MIMEMultipart
from email import encoders
from email.header import Header
from email.mime.text import MIMEText
from email.utils import parseaddr, formataddr
from email.mime.image import MIMEImage
import email
import yagmail
import smtplib
# import pygame; pygame.init()
import uuid
import os
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "EDM.settings")
import django; django.setup()
from core.models import EDMTasks
from django_redis import get_redis_connection
dbRedis = get_redis_connection()
import logging
logger = logging.getLogger('smtpProxy')
logger.setLevel(logging.INFO)
#handler = logging.handlers.SysLogHandler(address='/dev/log', facility="mail")
handler = logging.StreamHandler()
formatter = logging.Formatter("%(asctime)s %(levelname)s %(message)s","%Y%m%d %H:%M:%S")
handler.setFormatter(formatter)
logger.addHandler(handler)
from traceback import format_exc


# 获取异常信息
def get_exception_info() :
    lines = []
    for line in format_exc().strip().split('\n'):
        lines.append('  > ' + line)
    err_msg = '\n'.join(lines)
    return get_unicode(err_msg)


def _format_addr(s):
    name, addr = parseaddr(s)
    return formataddr((Header(name, 'utf-8').encode(), addr))


def cut(obj, sec):
    str_list = [obj[i:i + sec] for i in range(0, len(obj), sec)]
    return str_list


def get_unicode(string):
    st = type(string)
    if st.__name__ == 'unicode':
        return string
    else:
        return string.decode('utf-8', 'ignore')
    # charset = chardet.detect(string)['encoding']
    # if not charset:
    #     return string.decode('utf-8', 'ignore')
    # return string.decode(charset)


def get_string(code):
    if isinstance(code,unicode):
        try:
            return code.encode('utf-8')
        except:
            return code.encode('utf-8','ignore')
    if not isinstance(code,str):
        return str(code)
    return code


def textCut2List(text, sec):
    """
    :param text: unicode text
    :param sec: 切分长度
    :return: text_list
    """
    if not isinstance(text, unicode):
        text = get_unicode(text)
    text_list = []
    text_split = text.split('\n')
    for t in text_split:
        text_list.extend(cut(t, sec))
    return text_list


def Drawtext_pagame(text_list, ttc, ttc_size):
    height = len(text_list) * int(ttc_size * 1.1)
    im = Image.new("RGB", (ttc_size * 22, height), (255, 255, 255))
    ImageDraw.Draw(im)
    font = pygame.font.Font(ttc, int(ttc_size * 0.9))
    n = 0
    for text in text_list:
        rtext = font.render(text, True, (0, 0, 0), (255, 255, 255))
        sio = StringIO.StringIO()
        pygame.image.save(rtext, sio)
        sio.seek(0)
        line = Image.open(sio)
        # im.paste(line, (10, 5 + n * interval))
        im.paste(line, (ttc_size, n * int(ttc_size * 1.1)))
        sio.close()
        n += 1

    # name = "rymmx"
    # im.save("%s.png" % name)
    output_buffer = StringIO.StringIO()
    im.save(output_buffer, format='PNG')
    binary_data = output_buffer.getvalue()
    # base64_data = base64.b64encode(binary_data)
    # output_buffer.close()
    # print base64_data
    # return base64_data
    return binary_data


def Drawtext(text_list, ttc, ttc_size):
    """PIL"""
    height = len(text_list) * int(ttc_size * 1.1)
    im = Image.new("RGB", (ttc_size * 22, height), (255, 255, 255))
    ImageDraw.Draw(im)
    font = ImageFont.truetype(ttc, int(ttc_size * 0.9))
    n = 0
    for text in text_list:
        im_paste = Image.new("RGB", (ttc_size * 22, int(ttc_size * 1.1)), (255, 255, 255))
        dr = ImageDraw.Draw(im_paste)
        dr.text((0, 0), text, font=font, fill="#000000")
        sio = StringIO.StringIO()
        im_paste.save(sio, format='PNG')
        sio.seek(0)
        line = Image.open(sio)
        im.paste(line, (ttc_size, n * int(ttc_size * 1.1)))
        sio.close()
        n += 1

    output_buffer = StringIO.StringIO()
    im.save(output_buffer, format='PNG')
    binary_data = output_buffer.getvalue()
    return binary_data


def get_username():

    str_list = random.sample(string.lowercase, 8)
    random_str = ''.join(str_list)
    account = random_str + '@josephrobinettebiden.top'
    return account


def get_tasks():
    tasks = []
    # res_list = dbMysql.query("SELECT id,email,subject,content FROM edm_tasks WHERE result='wait'")
    objs = EDMTasks.objects.filter(result='wait')

    for obj in objs:
        tasks.append({
            'task_id': obj.id,
            'to': obj.email.lower(),
            'subject': obj.subject,
            'plain_text': obj.content,
            'html_text': '',
        })
    return tasks


def smtpSender4(task):
    text = task['plain_text']

    text_list = textCut2List(text, 20)
    ttc = '/root/email-delivery-marketing/wqy-zenhei.ttc'
    binary_data = Drawtext(text_list, ttc, ttc_size=40)

    # 准备邮件内容
    sed = random.choice([8, 10, 13, 15, 19, 22, 25, 27, 30])
    message_id_raw = str(uuid.uuid1()).replace('-', '')
    html_text = """
            <p><img border=0 src="cid:{CID}"/></p>
            """.format(CID=message_id_raw[:sed])

    body = task['subject']

    from_addr = get_username()
    to_addr = task['to'].lower()
    smtp_server = 'mail.josephrobinettebiden.top'

    yag = yagmail.SMTP(
        user=from_addr,
        smtp_ssl=False,
        host=smtp_server,
        port=25,
        smtp_skip_login=True
    )
    recipients, msg_string = yag.prepare_send(
        to=to_addr,
        subject=task['subject'],
        contents=[body, html_text],
        message_id=message_id_raw+'@josephrobinettebiden.top',
    )

    mailObj = email.message_from_string(msg_string)
    # from_name, _ = str(from_addr).split('@')
    from_name = dbRedis.get('EDM:from_name')
    if from_name:
        # from_name = get_string(from_name)
        from_name = from_name
    else:
        from_name, _ = str(from_addr).split('@')
    to_name, _ = str(to_addr).split('@')
    mailObj.replace_header('From', _format_addr(u'%s <%s>' % (get_unicode(from_name), get_unicode(from_addr))))
    # mailObj.replace_header('To', _format_addr('%s <%s>' % (to_name, to_addr)))
    mailObj.add_header('X-Mailer', 'Microsoft Outlook 16.0')

    # 添加可引用图片附件
    mime_img = MIMEImage(binary_data,_subtype='jpeg')
    mime_img.add_header('Content-Disposition', 'attachment', filename=message_id_raw[:9]+".jpeg")
    mime_img.add_header('Content-ID', '<%s>' % message_id_raw[:sed])
    mailObj.attach(mime_img)

    # 添加随机附件
    attachment_path = '{}.{}'.format(message_id_raw[3:13], message_id_raw[-3:])
    mime_attachment = MIMEBase('application', 'octet-stream', filename=attachment_path)
    mime_attachment.add_header('Content-Disposition', 'attachment', filename=attachment_path)
    mime_attachment.set_payload(message_id_raw * 29)
    encoders.encode_base64(mime_attachment)
    mailObj.attach(mime_attachment)

    for i in range(random.choice([0, 1, 2, 3])):
        message_id_raw_random = str(uuid.uuid1()).replace('-', '')
        attachment_path = '{}.{}'.format(message_id_raw_random[3:13], message_id_raw_random[15:19])
        mime_attachment = MIMEBase('application', 'octet-stream', filename=attachment_path)
        mime_attachment.add_header('Content-Disposition', 'attachment', filename=attachment_path)
        mime_attachment.set_payload(message_id_raw_random * 25)
        encoders.encode_base64(mime_attachment)
        mailObj.attach(mime_attachment)

    # 最终文本eml邮件
    mailObj_as_string = mailObj.as_string()
    # print mailObj_as_string

    # 发送邮件
    res_dict = {}
    tencent = '49.232.210.206'
    tianyi = "49.7.193.51"
    ucloud = "106.75.226.211"
    # smtp_proxy_list = [tencent, tianyi, "127.0.0.1", ucloud]
    smtp_proxy_list = [tianyi, "127.0.0.1", ucloud]
    smtp_proxy_list = [tianyi]
    # for smtp_proxy in [random.choice(smtp_proxy_list), random.choice(smtp_proxy_list), random.choice(smtp_proxy_list)]:
    for smtp_proxy in [random.choice(smtp_proxy_list), random.choice(smtp_proxy_list)]:
        try:
            server = smtplib.SMTP(smtp_proxy, 465)
            server.sendmail(from_addr, [to_addr], mailObj_as_string)
            server.quit()
            logger.info("%s 发送成功"%message_id_raw)
            logger.info(mailObj_as_string[:500])
            res_dict['message_id'] = message_id_raw
            return res_dict
        except Exception as e:
            logger.error(e.message)
            logger.warning( "发送失败")
            logger.warning("smtp_proxy:%s --> has trouble " % (smtp_proxy))
    res_dict['message_id'] = message_id_raw
    return res_dict


def main5():
    # 业务数据
    while True:

        edm_tasks_count = dbRedis.get('EDM:edm_tasks_count')
        if not edm_tasks_count:
            edm_tasks_count=0
        if int(edm_tasks_count) <= 0:
            logger.warning( "gevent.sleep(60) 剩余发送量为%s, 请及时充值。。。"% edm_tasks_count)
            time.sleep(60)
            continue

        tasks = get_tasks()

        if tasks:
            for task in tasks:

                # 暂停按钮
                while True:
                    edm_tasks_pause = dbRedis.get('EDM:edm_tasks_pause')
                    if edm_tasks_pause and edm_tasks_pause=="pause":
                        logger.warn('任务已经暂停。。。')
                        time.sleep(10)
                    else:
                        break

                try:
                    res_dict = smtpSender4(task)
                except Exception as e:
                    logger.error(e.message)
                    logger.error(get_exception_info())
                    res_dict = {"message_id": "00000000000000000000000000"}
                # print res_dict
                if res_dict.get('message_id'):
                    # update_task_sql = "UPDATE `edm_tasks` SET `message_id` = '%s',`result`='%s' WHERE `id` = %s" % (
                    #     res_dict['message_id'], 'sending', task['task_id'])
                    # Common.dbMysql.execute_rowcount(update_task_sql)
                    # print update_task_sql
                    obj = EDMTasks.objects.filter(id=task['task_id']).first()
                    obj.message_id=res_dict['message_id']
                    obj.result='sending'
                    obj.save()


                    edm_tasks_count = dbRedis.get('EDM:edm_tasks_count')
                    if edm_tasks_count:
                        dbRedis.set('EDM:edm_tasks_count', int(edm_tasks_count)-1)
                else:
                    logger.error( "to:%s 任务发送失败..." % task['to'])
                    # print task

                time.sleep(3.05)

        else:
            logger.info( "等待任务中:gevent.sleep(10)")
            time.sleep(10)


if __name__ == "__main__":

    main5()

